﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "FacadePattern.generated.h"

/**	外观模式 Facade Pattern
 *	描述
 *		外部与一个子系统的通信必须通过一个统一的外观对象进行，为子系统中的一组接口提供一个一致的界面，外观模式定义了一个高层接口，这个接口使得这一子系统更加容易使用。外观模式又称为门面模式，它是一种对象结构型模式。
 *	套路
 *		外观角色 （Facade）
 *			在客户端可以调用这个角色的方法，在外观角色中可以知道相关的子系统的功能和责任；在正常情况下，它将所有从客户端发来的请求委派到相应的子系统中去，传递给相应的子系统对象处理。
 *		子系统角色（SubSystem）
 *			在软件系统中可以有一个或者多个子系统角色，每一个子系统可以不是一个单独的类，而是一个类的集合，它实现子系统的功能；子系统并不知道外观（又称为门面）的存在，对于子系统而言，外观角色仅仅是另一个客户端而已。
 *	使用场景
 *		想要为访问一系列复杂的子系统提供一个统一的简单入口
 *		客户端与多个子系统之间存在很大的依赖性，引入外观类可以将子系统和客户端解耦
 *		在层次化结构中，可以使用外观模式定义系统中每一层的入口，层与层之间不直接产生联系
 *	优缺点
 *		优点
 *			降低了客户类与子系统类的耦合度，实现了子系统与客户之间的松耦合关系
 *			外观模式对客户屏蔽了子系统组件，从而简化了接口，减少了客户处理的对象数目并使子系统的使用更加简单。
 *			降低原有系统的复杂度和系统中的编译依赖性，并简化了系统在不同平台之间的移植过程
 *		缺点
 *			在不引入抽象外观类的情况下，增加新的子系统可能需要修改外观类或客户端的源代码，违背了“开闭原则”
 *			不能很好地限制客户使用子系统类，如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
 */

// 镜头序列轨道管理系统
UCLASS()
class MISCELLANEOUSPROJECT_API UCameraSubSystem : public UObject
{
	GENERATED_BODY()
public:
	void Play()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Camera start moving."));
	}

	void Stop()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Camera stop moving."));
	}
};

// 特效管理系统
UCLASS()
class MISCELLANEOUSPROJECT_API UVFXSubsystem : public UObject
{
	GENERATED_BODY()
public:
	void Play()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" VFX start playing."));
	}

	void Stop()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" VFX stop playing."));
	}
};

// 音频管理系统
UCLASS()
class MISCELLANEOUSPROJECT_API USFXSubsystem : public UObject
{
	GENERATED_BODY()
public:
	void Play()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" SFX start playing."));
	}

	void Stop()
	{
		// UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" SFX stop playing."));
	}
};

// 外观角色类
UCLASS()
class MISCELLANEOUSPROJECT_API UFacadeObject : public UObject
{
	GENERATED_BODY()
public:
	UFacadeObject()
	{
		CameraSubSystem = NewObject<UCameraSubSystem>();
		VFXSubsystem = NewObject<UVFXSubsystem>();
		SFXSubsystem = NewObject<USFXSubsystem>();
	}

	~UFacadeObject() {}

	// 开始过场剧场
	void PlayCutscene()
	{
		CameraSubSystem->Play();
		VFXSubsystem->Play();
		SFXSubsystem->Play();
	}

	// 结束过场剧场
	void StopCutscene()
	{
		CameraSubSystem->Stop();
		VFXSubsystem->Stop();
		SFXSubsystem->Stop();
	}

private:
	UPROPERTY()
	UCameraSubSystem* CameraSubSystem;

	UPROPERTY()
	UVFXSubsystem* VFXSubsystem;

	UPROPERTY()
	USFXSubsystem* SFXSubsystem;
};

// 调用测试
UCLASS()
class MISCELLANEOUSPROJECT_API AFacadeTestActor : public AActor
{
	GENERATED_BODY()

public:
	UPROPERTY()
	UFacadeObject* FacadeObject;

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override
	{
		FacadeObject = NewObject<UFacadeObject>();

		// 播放过场剧情
		FacadeObject->PlayCutscene();

		// UE_LOG(LogTemp, Warning, TEXT(" ---------------------------------------------- "));

		// 结束或跳过过场剧情
		FacadeObject->StopCutscene();
	}
};
